package com.foreveross.proxyip.infra.db.mongo;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.jasper.tagplugins.jstl.core.Set;

import com.foreveross.proxyip.infra.db.mongo.annotation.MongoColumn;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

/**
 * 反射工具类
 * 
 * @author fb
 */
public class MongoReflectUtils {

	/**
	 * 获取指定clazz中特定的mongo持久字段，包括所有父类递归
	 * 
	 * @param clazz
	 * @return List&lt;Field&gt;
	 */
	public static <T> List<Field> getFields(Class<T> clazz) {
		List<Field> fieldList = new ArrayList<Field>();
		setSuperFieldsByRecursion(fieldList, clazz);
		setMongoNeedFields(fieldList, clazz);
		
		return fieldList;
	}
	
	public static <T> DBObject createDBObject(T data) throws Exception  {
		BasicDBObject DBObject = new BasicDBObject();
		MongoColumn columnAn = null;
		String column = null;
		
		for (Field field : getFields(data.getClass())) {
			columnAn = field.getAnnotation(MongoColumn.class);
			column = columnAn.value();
			column = StringUtils.isEmpty(column) ? field.getName() : column;

			field.setAccessible(true);
			DBObject.append(column, field.get(data));
		}
		
		return DBObject;
	}
	
	/**
	 * 判断指定的class是否是java的8个原生类型
	 * 
	 * @param clazz
	 * @return
	 */
	public static <T> boolean isRawType(Class<T> clazz) {
		boolean resutl = false;
		
		if (clazz == String.class || clazz == Integer.class || clazz == Double.class ||
				clazz == Float.class || clazz == Boolean.class || clazz == Short.class ||
				clazz == Character.class || clazz == Byte.class) {
			resutl = true;
		} 
		
		return resutl;
	}
	
	/**
	 * 判断指定类型是否是原生类型
	 * 
	 * @param clazz
	 * @return
	 */
	public static <T> boolean isCollection(Class<T> clazz) {
		boolean resutl = false;
		
		if (clazz == List.class || clazz.isArray() || clazz == Set.class) {
			resutl = true;
		}
		
		return resutl;
	}
	
	private static <T> void setSuperFieldsByRecursion(List<Field> fieldList, Class<T> clazz) {
		Class<? super T> superClazz = clazz.getSuperclass();
		
		if (superClazz == Object.class) {
			return;
		}
		
		setSuperFieldsByRecursion(fieldList, superClazz);
		setMongoNeedFields(fieldList, superClazz);
	}
	
	private static <T> void setMongoNeedFields(List<Field> fieldList, Class<T> clazz) {
		Field fields[] = clazz.getDeclaredFields();
		
		for (Field field : fields) {
			if (field.isAnnotationPresent(MongoColumn.class)) {
				fieldList.add(field);
			}
		}
	}
}
